package com.railway.switchs.action.authority;

import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.railway.switchs.aspect.OperationLog;
import com.railway.switchs.base.BaseResponse;
import com.railway.switchs.constant.SystemConstant;
import com.railway.switchs.domain.dto.authority.AuthorityRole;
import com.railway.switchs.domain.dto.authority.AuthorityRolePermission;
import com.railway.switchs.domain.pojo.authority.AuthorityRolePojo;
import com.railway.switchs.domain.query.authority.AuthorityRolePermissionQuery;
import com.railway.switchs.domain.query.authority.AuthorityRoleQuery;
import com.railway.switchs.enums.EnumDateStyle;
import com.railway.switchs.enums.EnumReturnResult;
import com.railway.switchs.service.authority.IAuthorityRolePermissionService;
import com.railway.switchs.service.authority.IAuthorityRoleService;
import com.railway.switchs.utils.DateUtil;
import com.railway.switchs.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @ClassName RoleAction
 * @Author 魏梓晟
 * @Version 1.0
 **/
@Controller
@Slf4j
@RequestMapping("/back/role")
public class RoleAction {

    @Autowired
    private IAuthorityRoleService authorityRoleService;

    @Autowired
    private IAuthorityRolePermissionService authorityRolePermissionService;

    /**
     * 进入角色列表页面
     * @return
     */
    @RequestMapping(value = "/list",method = RequestMethod.GET)
    public String list(){
        return "role/list";
    }

    /**
     * 获取角色数据
     * @param query
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getList",method = RequestMethod.POST)
    public AuthorityRoleQuery getList(AuthorityRoleQuery query) {
        try {
            query = authorityRoleService.query(query);
            query.setCode(EnumReturnResult.RETURN_200.getCode());
        } catch (Exception e) {
            log.error("获取角色列表数据异常", e);
            query.setCode(EnumReturnResult.RETURN_404.getCode());
            query.setMsg("获取角色数据异常");
        }
        return query;
    }

    /**
     * 进入新增页面
     * @return
     */
    @RequestMapping(value = "/add",method = RequestMethod.GET)
    public String preAdd(){
        return "role/add";
    }

    /**
     * 新增角色
     * @param authorityRole
     * @param result
     * @return
     */
    @ResponseBody
    @OperationLog(billType ="1",actionType ="0" )
    @RequestMapping(value = "/add",method = RequestMethod.POST)
    public BaseResponse add(@Validated AuthorityRole authorityRole, BindingResult result) {
        BaseResponse response = new BaseResponse();
        try {
            if(result.hasErrors()){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("AuthorityRole-add参数有误");
                log.info("AuthorityRole-add参数有误："+result.getAllErrors().toString());
                return response;
            }
            //校验角色代码是否唯一
            if(checkUniqueRoleCode(authorityRole.getRoleCode())){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("该角色代码已存在");
                return response;
            }
            //校验角色名称是否唯一
            if(checkUniqueRoleName(authorityRole.getRoleName())){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("该角色名称已存在");
                return response;
            }
            authorityRoleService.add(authorityRole);
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("新增角色成功");
        } catch (Exception e) {
            log.error("新增角色异常",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("新增角色失败");
        }
        return response;
    }

    /**
     * 进入角色信息修改页面
     * @param id
     * @return
     */
    @RequestMapping(value = "/edit",method = RequestMethod.GET)
    public ModelAndView preEdit(Long id){
        ModelAndView mav = new ModelAndView();
        try{
            AuthorityRole authorityRole = authorityRoleService.get(id);
            mav.addObject("authorityRole",authorityRole);
            mav.setViewName("role/edit");
        }catch (Exception e){
            log.error("获取角色详情失败",e);
            mav.addObject(SystemConstant.ERROR_KEY,"系统异常");
            mav.setViewName("role/list");
        }
        return mav;
    }

    /**
     * 修改角色信息
     * @param authorityRole
     * @param result
     * @return
     */
    @ResponseBody
    @OperationLog(billType ="1",actionType ="1" )
    @RequestMapping(value = "/edit",method = RequestMethod.POST)
    public BaseResponse edit(@Validated AuthorityRole authorityRole, BindingResult result) {
        BaseResponse response = new BaseResponse();
        try {
            if(result.hasErrors()){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("AuthorityRole-edit参数有误");
                log.info("AuthorityRole-edit参数有误："+result.getAllErrors().toString());
                return response;
            }
            AuthorityRole authorityRoleTemp = authorityRoleService.get(authorityRole.getId());
            //校验角色代码是否被修改
            if(!authorityRoleTemp.getRoleCode().equals(authorityRole.getRoleCode())){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("角色代码不允许修改");
                return response;
            }
            //校验角色名称是否被修改
            if(authorityRoleTemp.getRoleName().equals(authorityRole.getRoleName())){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("角色名称不允许修改");
                return response;
            }
            authorityRoleService.edit(authorityRole);
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("修改角色信息成功");
        } catch (Exception e) {
            log.error("修改角色信息失败",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("修改角色信息失败");
        }
        return response;
    }

    /**
     * 删除用户
     * @param id
     * @return
     */
    @ResponseBody
    @OperationLog(billType ="1",actionType ="2" )
    @RequestMapping(value = "/delete",method = RequestMethod.POST)
    public BaseResponse delete(Long id){
        BaseResponse response = new BaseResponse();
        try{
            //删除角色的同时删除角色授权信息
            AuthorityRole authorityRole = authorityRoleService.get(id);
            AuthorityRolePermissionQuery authorityRolePermissionQuery = new AuthorityRolePermissionQuery();
            authorityRolePermissionQuery.setRoleCode(authorityRole.getRoleCode());
            List<AuthorityRolePermission> authorityRolePermissions = authorityRolePermissionService.getList(authorityRolePermissionQuery);
            if(StringUtil.isNotEmpty(authorityRolePermissions)){
                for(AuthorityRolePermission authorityRolePermission : authorityRolePermissions){
                    authorityRolePermissionService.delete(authorityRolePermission.getId());
                }
            }
            authorityRoleService.delete(id);
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("删除角色成功");
        }catch (Exception e){
            log.error("删除角色异常",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("删除角色失败");
        }
        return response;
    }

    /**
     * 角色授权页面
     * @param roleCode
     * @return
     */
    @RequestMapping(value = "/authorize",method = RequestMethod.GET)
    public ModelAndView preAuthorize(String roleCode) {
        ModelAndView mav = new ModelAndView();
        mav.addObject("roleCode",roleCode);
        mav.addObject("permissionStr",getPermissionCodeByRoleCode(roleCode));
        mav.setViewName("role/authorize");
        return mav;
    }

    /**
     * 通过角色代码获取授权的资源权限
     * @param roleCode
     * @return
     */
    private String getPermissionCodeByRoleCode(String roleCode) {
        AuthorityRolePermissionQuery query = new AuthorityRolePermissionQuery();
        query.setRoleCode(roleCode);
        List<AuthorityRolePermission> authorityRolePermissions = authorityRolePermissionService.getList(query);
        String permissionCodes = "";
        if(StringUtil.isNotEmpty(authorityRolePermissions)){
            for(AuthorityRolePermission authorityRolePermission : authorityRolePermissions){
                permissionCodes += authorityRolePermission.getPermissionCode() + ",";
            }
        }
        return permissionCodes;
    }

    /**
     * 角色授权
     * @param roleCode
     * @param permissionCodes
     * @return
     */
    @ResponseBody
    @OperationLog(billType ="1",actionType ="7" )
    @RequestMapping(value = "/authorize",method = RequestMethod.POST)
    public BaseResponse authorize(String roleCode,String permissionCodes) {
        BaseResponse response = new BaseResponse();
        try{
            String[] permissionArray = permissionCodes.split(",");
            if(StringUtil.isEmpty(permissionArray)){
                response.setCode(EnumReturnResult.RETURN_404.getCode());
                response.setMsg("请选择需要授权的资源");
                return response;
            }
            //新增角色权限前删除所有该角色原拥有的资源权限
            AuthorityRolePermissionQuery authorityRolePermissionQuery = new AuthorityRolePermissionQuery();
            authorityRolePermissionQuery.setRoleCode(roleCode);
            List<AuthorityRolePermission> authorityRolePermissions = authorityRolePermissionService.getList(authorityRolePermissionQuery);
            if(StringUtil.isNotEmpty(authorityRolePermissions)){
                for(AuthorityRolePermission authorityRolePermission : authorityRolePermissions){
                    authorityRolePermissionService.delete(authorityRolePermission.getId());
                }
            }
            //新增角色权限
            for(String permissionCode : permissionArray){
                AuthorityRolePermission authorityRolePermission = new AuthorityRolePermission();
                authorityRolePermission.setRoleCode(roleCode);
                authorityRolePermission.setPermissionCode(permissionCode);
                authorityRolePermissionService.add(authorityRolePermission);
            }
            response.setCode(EnumReturnResult.RETURN_200.getCode());
            response.setMsg("授权角色成功");
        }catch (Exception e){
            log.error("授权角色异常",e);
            response.setCode(EnumReturnResult.RETURN_404.getCode());
            response.setMsg("授权角色失败");
        }
        return response;
    }

    /**
     * 导出角色列表
     * @param response
     * @param query
     * @throws IOException
     */
    @RequestMapping(value = "/exports")
    public void exports(HttpServletResponse response,AuthorityRoleQuery query) throws IOException {
        ExcelWriter writer = null;
        OutputStream outputStream = response.getOutputStream();
        try {
            //添加响应头信息
            String fileName = URLEncoder.encode("角色列表" + DateUtil.DateToString(new Date(), EnumDateStyle.YYYYMMDDHHMMSS), "UTF-8");
            response.setHeader("Content-disposition", "attachment; filename=" + fileName + ".xls");
            response.setContentType("application/msexcel;charset=UTF-8");
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0);
            //实例化 ExcelWriter
            writer = new ExcelWriter(outputStream, ExcelTypeEnum.XLS, true);
            //实例化表单
            Sheet sheet = new Sheet(1, 2, AuthorityRolePojo.class);
            sheet.setSheetName("角色信息");
            //获取数据
            List<AuthorityRole> authorityRoles = authorityRoleService.getList(query);
            //输出
            writer.write(authorityRoles, sheet);
            writer.finish();
            outputStream.flush();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 校验是否已存在roleName
     * @param roleName
     * @return
     */
    private boolean checkUniqueRoleName(String roleName) {
        AuthorityRoleQuery query = new AuthorityRoleQuery();
        query.setRoleName(roleName);
        List<AuthorityRole> authorityRoleList = authorityRoleService.getList(query);
        if(StringUtil.isEmpty(authorityRoleList)){
            return false;
        }
        return true;
    }

    /**
     * 校验是否已存在roleCode
     * @param roleCode
     * @return
     */
    private boolean checkUniqueRoleCode(String roleCode) {
        AuthorityRoleQuery query = new AuthorityRoleQuery();
        query.setRoleCode(roleCode);
        List<AuthorityRole> authorityRoleList = authorityRoleService.getList(query);
        if(StringUtil.isEmpty(authorityRoleList)){
            return false;
        }
        return true;
    }

    /**
     * 获取所有角色数据
     * @param query
     * @return
     */
    @ResponseBody
    @RequestMapping(value = "/getAllList",method = RequestMethod.POST)
    public AuthorityRoleQuery getAllList(AuthorityRoleQuery query) {
        try {
            query.setData(authorityRoleService.getList(query));
            query.setCode(EnumReturnResult.RETURN_200.getCode());
        } catch (Exception e) {
            log.error("获取角色列表数据异常", e);
            query.setCode(EnumReturnResult.RETURN_404.getCode());
            query.setMsg("获取角色数据异常");
        }
        return query;
    }


}
